from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from ...database import get_db
from ...models.novel import Novel, NovelCharacter
from ...schemas.novel import (
    CharacterDetailResponse,
    Novel as NovelSchema,
    NovelWithCharacters,
    NovelCharacter as CharacterSchema
)
from ...core.response import success_response, error_response

router = APIRouter()


@router.get("/")
async def get_novels(db: AsyncSession = Depends(get_db)):
    try:
        # 获取小说列表
        stmt = select(Novel).where(Novel.is_active.is_(True))
        result = await db.execute(stmt)
        novels = result.scalars().all()
        
        novels_with_characters = []
        for novel in novels:
            char_stmt = select(NovelCharacter).where(
                NovelCharacter.novel_id == novel.id,
                NovelCharacter.is_active.is_(True)
            ).order_by(NovelCharacter.importance_level.desc())
            char_result = await db.execute(char_stmt)
            characters = char_result.scalars().all()
            
            novel_data = NovelSchema.model_validate(novel)
            novel_with_characters = NovelWithCharacters(
                **novel_data.model_dump(),
                characters=[
                    CharacterSchema.model_validate(char) for char in characters
                ]
            )
            novels_with_characters.append(novel_with_characters)
        
        return success_response(
            data=novels_with_characters,
            message="获取小说列表成功"
        )
    except Exception as e:
        return error_response(
            message=f"获取小说列表失败: {str(e)}",
            code=500,
            status_code=500
        )


@router.get("/{novel_id}")
async def get_novel_detail(novel_id: int, db: AsyncSession = Depends(get_db)):
    try:
        stmt = select(Novel).where(
            Novel.id == novel_id, 
            Novel.is_active.is_(True)
        )
        result = await db.execute(stmt)
        novel = result.scalar_one_or_none()
        
        if not novel:
            return error_response(
                message="小说不存在",
                code=404,
                status_code=404
            )
        
        # 获取活跃的角色列表，按重要程度排序
        char_stmt = select(NovelCharacter).where(
            NovelCharacter.novel_id == novel_id,
            NovelCharacter.is_active.is_(True)
        ).order_by(NovelCharacter.importance_level.desc())
        char_result = await db.execute(char_stmt)
        characters = char_result.scalars().all()
        
        # 构建响应数据
        novel_data = NovelSchema.model_validate(novel)
        novel_with_characters = NovelWithCharacters(
            **novel_data.model_dump(),
            characters=[
                CharacterSchema.model_validate(char) for char in characters
            ]
        )
        
        return success_response(
            data=novel_with_characters,
            message="获取小说详情成功"
        )
    except Exception as e:
        return error_response(
            message=f"获取小说详情失败: {str(e)}",
            code=500,
            status_code=500
        )


@router.get("/{novel_id}/characters/{character_id}")
async def get_character_detail(
    novel_id: int, 
    character_id: int, 
    db: AsyncSession = Depends(get_db)
):
    try:
        stmt = select(NovelCharacter).where(
            NovelCharacter.id == character_id,
            NovelCharacter.novel_id == novel_id,
            NovelCharacter.is_active.is_(True)
        )
        result = await db.execute(stmt)
        character = result.scalar_one_or_none()
        
        if not character:
            return error_response(
                message="角色不存在",
                code=404,
                status_code=404
            )
        
        return success_response(
            data=CharacterSchema.model_validate(character),
            message="获取角色详情成功"
        )
    except Exception as e:
        return error_response(
            message=f"获取角色详情失败: {str(e)}",
            code=500,
            status_code=500
        ) 